package com.ganbo.dingding.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.ganbo.dingding.config.DingDingConfig;
import com.ganbo.dingding.domain.DingdingGroup;
import com.ganbo.dingding.domain.DingdingMessage;
import com.ganbo.dingding.enums.MessageStatus;
import com.ganbo.dingding.mapper.DingdingGroupMapper;
import com.ganbo.dingding.mapper.DingdingMessageMapper;
import com.ganbo.dingding.service.GroupMessageService;
import com.ganbo.dingding.utils.SignatureUtil;
import com.ganbo.dingding.vo.SendGroupMessageReq;
import com.ynt.pay.common.utils.FastJsonUtil;
import com.ynt.pay.common.utils.ResponseData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;

/**
 * 钉钉群消息
 *
 * @Author: ganbo
 * @Date: 2019/12/2 16:33
 */
@Slf4j
@Service
public class GroupMessageServiceImpl implements GroupMessageService {

    @Autowired
    DingdingGroupMapper dingdingGroupMapper;
    @Autowired
    DingdingMessageMapper dingdingMessageMapper;
    @Autowired
    DingDingConfig dingDingConfig;

    /**
     * 发送钉钉群消息
     *
     * @param req
     * @return
     */
    @Override
    public ResponseData sendGroupMessage(SendGroupMessageReq req) {
        String code = req.getCode();
        String content = req.getContent();

        String key = "ynt:notice:dingding:groups";
        DingdingGroup group = dingdingGroupMapper.selectOne(new QueryWrapper<DingdingGroup>().eq("code", code));
        if (group == null) return ResponseData.error("500", "钉钉群code:" + code + "对应的群不存在");

        DingdingMessage message = new DingdingMessage();
        message.setContent(content);
        message.setGroupId(group.getId());
        message.setStatus(MessageStatus.NO_SEND.name());
        dingdingMessageMapper.insert(message);

        //屏蔽at指定号码功能
        try {
            //发送消息
            OapiRobotSendResponse response = sendGroupMessage(group, message, req.getAtMobiles(), req.isAtAll());
            if (0 == response.getErrcode() && "ok".equals(response.getErrmsg())) {  //发送成功
                message.setStatus(MessageStatus.SUCCESS.name());
                dingdingMessageMapper.updateById(message);
            } else {
                log.error("钉钉告警消息发送失败，钉钉服务器返回内容:{}", FastJsonUtil.objectTOJsonString(response));
                updateMessageStatus(message, MessageStatus.FAIL, FastJsonUtil.objectTOJsonString(response));
            }
        } catch (Exception e) {
            log.error("钉钉告警消息发送失败，异常信息======>", e);
            updateMessageStatus(message, MessageStatus.FAIL, e.getMessage());
            return ResponseData.error("500", e.getMessage());
        }
        return ResponseData.success();
    }

    /**
     * 定时扫描重试发送失败的消息
     */
    @Override
    public void groupMessageFailRetry() {
        List<DingdingMessage> messages = dingdingMessageMapper.selectList(new QueryWrapper<DingdingMessage>().eq("status", MessageStatus.FAIL.name()).or().eq("status", MessageStatus.NO_SEND.name()));
        if (CollectionUtils.isEmpty(messages)) return;

        messages.forEach(message -> {
            try {
                log.info("定时轮询任务-重新发送失败消息,messageId:{},content:{}", message.getId(), message.getContent());
                Long groupId = message.getGroupId();
                DingdingGroup group = dingdingGroupMapper.selectById(groupId);
                Thread.sleep(5000); //每条消息间隔5秒
                //发送消息
                OapiRobotSendResponse response = sendGroupMessage(group, message, Collections.EMPTY_LIST, true);  //这里发送失败后的消息重新发送,都是at所有人
                if (0 == response.getErrcode() && "ok".equals(response.getErrmsg())) {  //发送成功
                    message.setStatus(MessageStatus.SUCCESS.name());
                    dingdingMessageMapper.updateById(message);
                } else {
                    log.error("钉钉告警消息发送失败，钉钉服务器返回内容:{}", FastJsonUtil.objectTOJsonString(response));
                }
            } catch (Exception e) {
                log.error("定时轮询任务-钉钉告警消息发送失败，异常信息======>", e);
            }
        });
    }


    private OapiRobotSendResponse sendGroupMessage(DingdingGroup group, DingdingMessage message, List<String> atMobiles, boolean isAtAll) throws Exception {
        String url = group.getWebHook() + "&timestamp=" + System.currentTimeMillis() + "&sign=" + SignatureUtil.getRebootSign(group.getSign());
        DingTalkClient client = new DefaultDingTalkClient(url);
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
        text.setContent(message.getContent());   //
        request.setMsgtype("text"); //消息类型为文本消息设置消息内容

        request.setText(text);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        if (isAtAll) {
            at.setIsAtAll("true");  //设置要at的人
        } else if (!CollectionUtils.isEmpty(atMobiles)) {
            at.setAtMobiles(atMobiles);  //设置要@的人的电话号码
        }
        request.setAt(at);
        OapiRobotSendResponse response = client.execute(request);
        return response;
    }

    private void updateMessageStatus(DingdingMessage message, MessageStatus status, String remark) {
        message.setStatus(status.name());
        message.setRemark(remark);
        dingdingMessageMapper.updateById(message);
    }

}
